package com.tang.plugin.ui;

import com.intellij.icons.AllIcons;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.table.JBTable;
import com.tang.plugin.utils.ActionToolbarUtils;

import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 可编辑的表格
 */
public class EditableTable extends JPanel {

    private JScrollPane scrollPane;
    private JComponent toolbar;
    private JBTable table;
    private EditableTableModel tableModel;

    private String[] header;
    private boolean[] isEditable;

    public EditableTable(String[] header, boolean[] isEditable) {
        this.header = header;
        this.isEditable = isEditable;
        tableModel = new EditableTableModel();

        scrollPane = new JBScrollPane();
        table = new JBTable();
        setLayout(new BorderLayout());

        ArrayList<ActionToolbarUtils.Action> actions = new ArrayList<>();
        actions.add(new ActionToolbarUtils.Action(AllIcons.General.Add, true, "添加", () -> {
            tableModel.add();
            table.updateUI();
        }));
        actions.add(new ActionToolbarUtils.Action(AllIcons.General.Remove, true, "删除", () -> {
            int selectedRow = table.getSelectedRow();
            if (selectedRow == -1) {
                return;
            }
            tableModel.remove(selectedRow);
            table.updateUI();
        }));
        actions.add(new ActionToolbarUtils.Action(AllIcons.General.CopyHovered, true, "复制", () -> {
            int selectedRow = table.getSelectedRow();
            if (selectedRow == -1) {
                return;
            }
            tableModel.copy(selectedRow);
            table.updateUI();
        }));

        toolbar = ActionToolbarUtils.create("toolbar", actions);
        add(toolbar, BorderLayout.NORTH);

        scrollPane.setViewportView(table);
        add(scrollPane, BorderLayout.CENTER);

        table.setFillsViewportHeight(true);
        table.setShowVerticalLines(true);
        table.setShowHorizontalLines(true);
        table.setModel(tableModel);
        table.putClientProperty("terminateEditOnFocusLost", true);
    }

    public void setToolbarVisible(boolean isVisible) {
        toolbar.setVisible(isVisible);
    }

    public void setPairData(Map<String, String> data) {
        List<List<String>> dataList = new ArrayList<>();
        data.forEach((k, v) -> {
            ArrayList<String> list = new ArrayList<>();
            list.add(k);
            list.add(v);
            dataList.add(list);
        });
        tableModel.setData(dataList);
        tableModel.fireTableDataChanged();
        table.updateUI();
    }

    public Map<String, String> getPairResult() {
        Map<String, String> result = new HashMap<>();
        for (int i = 0; i < table.getRowCount(); i++) {
            String key = table.getValueAt(i, 0).toString();
            String value = table.getValueAt(i, 1).toString();
            if (key == null || key.length() == 0) {
                continue;
            }
            result.put(key, value);
        }
        return result;
    }

    public void addChangeListener(ChangeListener listener) {
        tableModel.addTableModelListener(listener::invoke);
    }

    private class EditableTableModel extends DefaultTableModel {

        public void add() {
            String[] rows = new String[getColumnCount()];
            for (int i = 0; i < getColumnCount(); i++) {
                rows[i] = "";
            }
            addRow(rows);
            fireTableDataChanged();
        }

        public void remove(int row) {
            removeRow(row);
            fireTableDataChanged();
        }

        public void copy(int row) {
            String[] rows = new String[getColumnCount()];
            for (int i = 0; i < getColumnCount(); i++) {
                rows[i] = getValueAt(row, i).toString();
            }
            addRow(rows);
            fireTableDataChanged();
        }

        public void setData(List<List<String>> fileTemplates) {
            while (getRowCount() > 0) {
                removeRow(0);
            }
            if (fileTemplates == null || fileTemplates.size() == 0) {
                return;
            }
            fileTemplates.forEach((templates) -> addRow(templates.toArray()));
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            if (isEditable != null && isEditable.length > column) {
                return isEditable[column];
            }
            return super.isCellEditable(row, column);
        }

        @Override
        public String getColumnName(int column) {
            if (header != null && header.length > column) {
                return header[column];
            }
            return super.getColumnName(column);
        }

        @Override
        public int getColumnCount() {
            if (header != null) {
                return header.length;
            }
            return super.getColumnCount();
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return String.class;
        }
    }

    public interface ChangeListener {
        void invoke(TableModelEvent event);
    }

}
